Passed
Push — master ( ae58d1...b549a3 )
by Barry
01:11
created

helpers.js ➔ jsonEllipsify   B

Complexity

Conditions 6
Paths 13

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
c 1
b 0
f 0
nc 13
nop 2
dl 0
loc 21
rs 8.7624
1
/*
2
=====fsnip======
3
4
fsnip is a command line utility to extract and modify json from a file.
5
6
*/
7
const fs = require('fs')
8
const stringify = require('json-stringify-pretty-compact')
9
const chalk = require('chalk')
10
const {runOption} = require('./runOptions.js')
11
12
export function cli (args) {
13
  if (args.length === 3 && args[2] === '--help') {
14
    console.info('fsnip is a tool for extracting json snippets from json files.\n\n' +
15
                 'Usage:\n' + '' +
16
                 'TODO still \n' +
17
                 '  fsnip FILE [options [arguments]]    process the file and output the result to the console\n' +
18
                 '  FILE         Specifies the file to process.\n' +
19
                 '  --ellipsify  replaces the passed object with ellipses (...)\n' +
20
                 '                 but excludes any keys which follow prepended by ~\n' +
21
                 '                 eg. fsnip myfile.json --ellipsify $..address ~postcode')
22
  } else if (args.length >= 3) {
23
    try {
24
      var txt = fs.readFileSync(args[2]).toString()
25
    } catch (err) {
26
      console.error(chalk.redBright("unable to read file '" + args[2] + "'"))
27
    }
28
    if (typeof txt !== 'undefined') {
29
      console.info(fsnipDo(args.slice(3), txt))
30
    }
31
  } else { // we couldn't recognise the format on the command line
32
    console.error(chalk.redBright('Unrecognised arguments passed to fsnip. See fsnip --help'))
33
  }
34
}
35
36
function fsnipDo (cmdOpts, inputText) {
37
  // does the processing of the fsnip command
38
  // inputText is the text we want to modify
39
  if (cmdOpts === null || cmdOpts.length === 0) { return inputText } // no processing required as no options passed in
40
  var src = { // a temporary structure containing the text we are working on its type eg. 'json' (which is set later)
41
    text: inputText,
42
    type: '',
43
    outputOptions: {},
44
    error: [],
45
    json: null,
46
    plain: null
47
  }
48
49
  parseOptions()
50
  postProcess(src)
51
  return src.error.length === 0 ? src.text : chalk.redBright(src.error)
52
53
  function parseOptions () {
54
    // now we are going to parse through the options and arguments to extract individual options together with their arguments
55
    var cmdOpt = '' // current option from the cmdOptsString list
56
    var cmdArgs = [] // array containing any arguments for the cmdOpt
57
    for (var i = 0; i < cmdOpts.length; i++) {
58
      if (cmdOpts[i].substr(0, 2) === '--') { // this is a new option eg. --ellipsify
59
        processOption()
60
        cmdOpt = cmdOpts[i] // store the new option we have found
61
        cmdArgs = [] // reset ready for any new arguments
62
      } else {
63
        // this must be an argument for the current option
64
        if (cmdOpt === '') { // error if we don't currently have an option
65
          src.error.push("invalid argument '" + cmdOpts[i] + "' passed without valid option to fsnip")
66
        } else {
67
          cmdArgs.push(cmdOpts[i])
68
        }
69
      }
70
    }
71
    processOption()
72
73
    function processOption () {
74
      // process/run any option we've found
75
      if (cmdOpt !== '') {
76
        runOption(cmdOpt, cmdArgs, src)
77
      }
78
    }
79
  }
80
}
81
82
function postProcess (inpObj) {
83
  // does any post process tidying up
84
  if (inpObj.type === 'json') {
85
    // stringify as required
86
    let opts = inpObj.outputOptions
87
    if (opts.maxLength === 'infinity' && opts.margins === false) {
88
      inpObj.text = JSON.stringify(inpObj.json)
89
    } else if (opts.maxLength === 0 && opts.margins === false) {
90
      inpObj.text = JSON.stringify(inpObj.json, null, opts.indent)
91
    } else {
92
      inpObj.text = stringify(inpObj.json, opts)
93
    }
94
    // now replace any placeholders. The placeholders are valid JSON but what we replace them with may not be valid JSON
95
    inpObj.text = inpObj.text.replace(/\[\s*"fsnipPlaceholderArrEllipses"\s*\]/g, '[...]')
96
    inpObj.text = inpObj.text.replace(/\{\s*"fsnipPlaceholderObj"\s*:\s*"Ellipses"\s*\}/g, '{...}') // do this separately to the one below so that if the object is empty it appears all on one line
97
    inpObj.text = inpObj.text.replace(/"fsnipPlaceholderObj"\s*:\s*"Ellipses"/g, '...')
98
    inpObj.text = inpObj.text.replace(/"fsnipPlaceholderStrEllipses"/g, '"..."')
99
  } else if (inpObj.type === 'plain') {
100
    inpObj.text = inpObj.plain.trim()
101
  }
102
}
103